package com.coda.service.impl;

import com.coda.adminVo.login.CaptchaVo;
import com.coda.adminVo.login.LoginVo;
import com.coda.adminVo.system.user.SystemUserInfoVo;
import com.coda.adminVo.system.user.SystemUserItemVo;
import com.coda.constant.MessageConstant;
import com.coda.constant.RedisConstant;
import com.coda.context.BaseContext;
import com.coda.entity.SystemUser;
import com.coda.exception.AccountException;
import com.coda.exception.CaptchaCodeException;
import com.coda.exception.StatusIsStartException;
import com.coda.mapper.SystemUserMapper;
import com.coda.properties.JwtAdminProperties;
import com.coda.service.LoginService;
import com.coda.utils.JwtUtil;
import com.wf.captcha.SpecCaptcha;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SystemUserMapper systemUserMapper;
    @Autowired
    private JwtAdminProperties jwtAdminProperties;


    /**
     * 生成图形验证码
     *
     * @return
     */
    @Override
    public CaptchaVo getCaptcha() {
        //创建图形验证码对象，设置宽高长度
        SpecCaptcha specCaptcha = new SpecCaptcha(130, 48, 4);
        //将其转换为小写（客户端输入验证码的时候不区分大小写）作为redis value
        String code = specCaptcha.text().toLowerCase();
        //生成redis  key，方便后端查找对应的value
        String key = RedisConstant.ADMIN_LOGIN_PREFIX + UUID.randomUUID();
        //设置redis value
        redisTemplate.opsForValue().set(key, code,
                RedisConstant.ADMIN_LOGIN_CAPTCHA_TTL_SEC,
                TimeUnit.SECONDS);

        return new CaptchaVo(specCaptcha.toBase64(), key);
    }

    /**
     * 登录
     *
     * @param loginVo
     * @return
     */
    @Override
    public String login(LoginVo loginVo) {
        //判断验证码是否正确
        //判断客户端是否输入验证码
        if (loginVo.getCaptchaCode() == null) {
            throw new CaptchaCodeException(MessageConstant.CAPTCHA_CODE_NULL);
        }

        //获取验证码
        String code = (String) redisTemplate.opsForValue().get(loginVo.getCaptchaKey());
        //根据客户端输入的验证码是否有效
        if (code == null) {
            throw new CaptchaCodeException(MessageConstant.CAPTCHA_CODE_OVERDUE);
        }
        //判断客户端输入的验证码是否正确
        if (!(code.equals(loginVo.getCaptchaCode().toLowerCase()))) {
            throw new CaptchaCodeException(MessageConstant.CAPTCHA_CODE_ERR);
        }

        //判断用户名或密码是否正确
        //判断用户名是否存在
        SystemUser systemUser = systemUserMapper.getSystemUser(loginVo.getUsername());
        if (systemUser == null) {
            throw new AccountException(MessageConstant.ACCOUNT_NOT_EXISTS);
        }
        //判断密码是否存在
        if (loginVo.getPassword() == null) {
            throw new AccountException(MessageConstant.PASSWORD_NOT_EXISTS);
        }
        //判断用户状态
        if (systemUser.getStatus() == 0) {
            throw new StatusIsStartException(MessageConstant.USER_STATUS_STOP);
        }
        //判断用户名和密码是正确
        String password = DigestUtils.md5Hex(loginVo.getPassword());
        if (!(systemUser.getPassword().equals(DigestUtils.md5Hex(loginVo.getPassword())))) {
            throw new AccountException(MessageConstant.ACCOUNT_ERR);
        }

        //登录成功后生成jwt令牌
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", systemUser.getId());
        String token = JwtUtil.createJWT(
                jwtAdminProperties.getAdminSecretKey(),
                jwtAdminProperties.getAdminTtl(),
                claims);
        return token;
    }

    /**
     * 获取登录用户信息
     *
     * @return
     */
    @Override
    public SystemUserInfoVo getSystemUserInfo() {
        SystemUserItemVo systemUserItemVo = systemUserMapper.getById(BaseContext.getCurrentId());
        SystemUserInfoVo systemUserInfoVo = new SystemUserInfoVo();
        systemUserInfoVo.setName(systemUserItemVo.getName());
        systemUserInfoVo.setAvatarUrl(systemUserItemVo.getAvatarUrl());
        return systemUserInfoVo;
    }
}
